package org.itzixi.netty.strategy;

import cn.hutool.core.date.DateUtil;
import com.a3test.component.idworker.IdWorkerConfigBean;
import com.a3test.component.idworker.Snowflake;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import io.netty.channel.Channel;
import io.netty.channel.group.ChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;
import org.itzixi.enums.MsgTypeEnum;
import org.itzixi.netty.rabbitmq.MessagePublisher;
import org.itzixi.netty.single.ChannelGroupSingleton;
import org.itzixi.netty.websocket.UserChannelCache;
import org.itzixi.pojo.netty.ChatMsg;
import org.itzixi.pojo.netty.DataContent;
import org.itzixi.utils.JsonUtils;
import org.itzixi.utils.LocalDateUtils;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;

@Slf4j
public class MessageHandlerStrategy {
    private static final ChannelGroup channelGroup = ChannelGroupSingleton.getInstance();

    private static final Map<MsgTypeEnum, Consumer<Map<String, Object>>> functionMap = new HashMap<>(16);



    static {
        try {
            initConsumerMap();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void initConsumerMap(){
        functionMap.put(MsgTypeEnum.CONNECT_INIT, MessageHandlerStrategy::handleInitMsg);
        functionMap.put(MsgTypeEnum.WORDS, MessageHandlerStrategy::handleWordsMsg);
        functionMap.put(MsgTypeEnum.IMAGE, MessageHandlerStrategy::handleImageMsg);
        functionMap.put(MsgTypeEnum.VIDEO, MessageHandlerStrategy::handleVideoMsg);
        functionMap.put(MsgTypeEnum.VOICE, MessageHandlerStrategy::handleVoiceMsg);
    }

    private static void handleVoiceMsg(Map<String, Object> dataContentMap) {
        handleWordsMsg(dataContentMap);
    }

    public static void handleMsgByType(Map<String, Object> dataMap) {
        DataContent dataContent = (DataContent)dataMap.get("dataContent");
        ChatMsg chatMsg = dataContent.getChatMsg();
        Integer msgType = chatMsg.getMsgType();
        MsgTypeEnum msgTypeEnum = MsgTypeEnum.getMsgTypeEnum(msgType);
        functionMap.get(msgTypeEnum).accept(dataMap);

    }


    /**
     * 处理第一次的消息
     * @param dataContentMap
     */
    public static void handleInitMsg(Map<String, Object> dataContentMap)  {
//        System.out.println(2222);
        DataContent dataContent = (DataContent)dataContentMap.get("dataContent");
        Channel channel = (Channel)dataContentMap.get("channel");
        // 把channel和userId关联起来
        String senderId = dataContent.getChatMsg().getSenderId();
        String currentChannelId = channel.id().asLongText();
        UserChannelCache.putMultiChannels(senderId, channel);
        log.info("用户id是：{}, 对应的channelList是：{}", senderId, UserChannelCache.getMultiChannels(senderId));
        UserChannelCache.putChannelOfUser(currentChannelId, senderId);

    }


    /**
     * 处理文字消息类型
     * @param dataContentMap
     * @return
     */
    public static void handleWordsMsg(Map<String, Object> dataContentMap)  {
        // 此处异步解耦，保存信息到数据库


        DataContent dataContent = (DataContent)dataContentMap.get("dataContent");
        ChatMsg chatMsg = dataContent.getChatMsg();
        String receiverId = chatMsg.getReceiverId();
        List<Channel> receiveChannelList = UserChannelCache.getMultiChannels(receiverId);
        if (CollectionUtils.isEmpty(receiveChannelList)){
            // 如果为空则表示断线或者离线状态
            chatMsg.setIsReceiverOnLine(false);
        } else {
            chatMsg.setIsReceiverOnLine(true);
            sendMessage(receiveChannelList, dataContent, chatMsg);

        }
        String senderId = chatMsg.getSenderId();
        Channel channel = (Channel)dataContentMap.get("channel");
        List<Channel> myOtherChannelList = UserChannelCache.getMyOtherChannel(senderId, channel.id().asLongText());
        // 给其它同步设备也发送消息
        sendMessage(myOtherChannelList, dataContent, chatMsg);
        // 把聊天信息作为mq的消息发送给消费者进行处理
        try {
            MessagePublisher.sendMsgToSave(chatMsg);
        } catch (Exception e) {
            log.error("发送聊天消息到rabbitmq失败:{},{}", e, e.getMessage());
            throw new RuntimeException(e);
        }

    }

    private static void setChatMsgId(ChatMsg chatMsg){
        // 雪花算法得到id
        Snowflake snowflake = new Snowflake(new IdWorkerConfigBean());
        String nextId = snowflake.nextId();
        log.info("Snowflake 的id为：{}", nextId);
        String idStr = IdWorker.getIdStr();
        log.info("mybatisPlus 的id为：{}", idStr);
        chatMsg.setMsgId(nextId);
    }


    public static void handleImageMsg(Map<String, Object> dataContentMap)  {
        handleWordsMsg(dataContentMap);
    }

    public static void handleVideoMsg(Map<String, Object> dataContentMap)  {
        handleWordsMsg(dataContentMap);
    }

    private static void sendMessage(List<Channel> channelList, DataContent dataContent, ChatMsg chatMsg){
        channelList.stream().filter(Objects::nonNull).forEach(c -> {
            Channel resultChannel = channelGroup.find(c.id());
            if (Objects.equals(chatMsg.getMsgType(), MsgTypeEnum.VOICE.type)){
                chatMsg.setIsRead(false);
            }
            dataContent.setChatMsg(chatMsg);
            String chatTimeFormat = DateUtil.format(chatMsg.getChatTime(), LocalDateUtils.DATETIME_PATTERN_2);
            dataContent.setChatTime(chatTimeFormat);
            resultChannel.writeAndFlush(new TextWebSocketFrame(JsonUtils.objectToJson(dataContent)));
        });
    }














}
